home *** CD-ROM | disk | FTP | other *** search
/ Resource Library: Multimedia / Resource Library: Multimedia.iso / maestro / source / timeline / instrumn.c < prev    next >
Encoding:
Text File  |  1993-06-15  |  22.6 KB  |  549 lines

  1. /*
  2.  * Copyright (c) 1990, 1991 Stanford University
  3.  *
  4.  * Permission to use, copy, modify, and distribute this software and 
  5.  * its documentation for any purpose is hereby granted without fee, provided
  6.  * that (i) the above copyright notices and this permission notice appear in
  7.  * all copies of the software and related documentation, and (ii) the name
  8.  * Stanford may not be used in any advertising or publicity relating to
  9.  * the software without the specific, prior written permission of
  10.  * Stanford.
  11.  * 
  12.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  13.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  14.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  15.  *
  16.  * IN NO EVENT SHALL STANFORD BE LIABLE FOR ANY SPECIAL, INCIDENTAL,
  17.  * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES
  18.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT
  19.  * ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY,
  20.  * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
  21.  * SOFTWARE.
  22.  */
  23.  
  24. /* $Header: /Source/Media/collab/TimeLine/RCS/instrument.c,v 1.2 91/10/03 17:39:01 chua Exp Locker: drapeau $ */
  25. /* $Log:    instrument.c,v $
  26.  * Revision 1.2  91/10/03  17:39:01  chua
  27.  * In DrawNote, change the parameters to DrawBox.  This is to correct an 
  28.  * error where if the zoom level is high, notes do not get drawn and
  29.  * erased properly.
  30.  * 
  31.  * Revision 1.1  91/09/30  22:38:54  chua
  32.  * Removed a printf statement.
  33.  * 
  34.  * Revision 1.0  91/09/30  16:57:54  chua
  35.  * In InstrumentNew, instead of just assigning instrument->port to port, copy each entry
  36.  * manually.
  37.  * 
  38.  * Revision 0.71  91/09/26  18:01:15  chua
  39.  * In FreeInstrument, free the instrument->port.
  40.  * 
  41.  * Revision 0.70  91/09/25  14:05:02  chua
  42.  * Changed InitInstInfoWindow to InitEditInfoWindow.
  43.  * 
  44.  * Revision 0.69  91/09/25  13:49:14  chua
  45.  * Changed the instrument field, instInfo, to editInfo.
  46.  * Changed InstrumentInfo to EditInfo.
  47.  * 
  48.  * Revision 0.68  91/09/20  11:40:27  chua
  49.  * 
  50.  * Removed braces at line 273.
  51.  * 
  52.  * Revision 0.67  91/09/19  17:28:49  chua
  53.  * Make sure that variables are initialized properly.  Change formatting slightly,
  54.  * so that (if, for, while) statements with only one statement in them will not have
  55.  * braces.
  56.  * 
  57.  * Revision 0.66  91/09/17  17:16:23  chua
  58.  * In InstrumentNew, correct some errors (line 275, 279) where it should be
  59.  * instrument->port instead of just port.
  60.  * 
  61.  * Revision 0.65  91/09/16  15:00:00  chua
  62.  * In InstrumentNew, add a new parameter, appName, which indicates the name of the
  63.  * application for this instrument.  This parameter is used when the application is not
  64.  * open, since there won't be a port number then.
  65.  * 
  66.  * Also, in InstrumentNew, initialize the port structure and allocate memory for it.
  67.  * 
  68.  * Added a new function, AddInstrument, which takes a port and tlFrame as parameters, and
  69.  * adds the instrument to the instrument list.
  70.  * 
  71.  * Revision 0.64  91/08/27  18:17:36  chua
  72.  * In FreeInstrumentList, before doing a DestroySender, check that the 
  73.  * application is still alive.
  74.  * 
  75.  * Revision 0.63  91/08/21  16:53:47  chua
  76.  * In the InstrumentNew routine, the call to OpenAppsFindIcon now takes the instrument
  77.  * as the parameter, instead of just the port.
  78.  * 
  79.  * Revision 0.62  91/08/19  19:18:28  chua
  80.  * In FreeInstrumentList, do a DestroySender.
  81.  * 
  82.  * Revision 0.61  91/08/16  16:59:42  chua
  83.  * In InstrumentNew, initialize the new variable, icon, which points to the pixmap
  84.  * image of the icon for the application.
  85.  * 
  86.  * In InstrumentDrawIcon, introduce a new type, Waiting, which will draw a red
  87.  * background for the icon image.
  88.  * 
  89.  * Revision 0.60  91/08/09  15:13:19  chua
  90.  * In FindInstrument, if relativePosition is a negative number, return NULL.
  91.  * 
  92.  * Revision 0.59  91/08/08  14:25:11  chua
  93.  * In the InstrumentNew procedure, before creating a new sender, check that the application
  94.  * does exist.
  95.  * 
  96.  * Revision 0.58  91/07/22  15:16:58  chua
  97.  * Added a new procedure, DrawPauseMarkers, to draw the pause markers.  This procedure is called
  98.  * by InstrumentDraw, and the markers are drawn just before the notes are drawn.
  99.  * 
  100.  * Revision 0.57  91/07/18  15:05:47  chua
  101.  * *** empty log message ***
  102.  * 
  103.  * Revision 0.56  91/07/17  10:20:10  chua
  104.  * In the DrawNote routine, set x to take into account the fact that the starting
  105.  * position of the canvas may not be at time 0 but at some arbitrary time.
  106.  * 
  107.  * In the InstrumentDrawNotes function, draw the note only if it is within the current
  108.  * canvas area (which only covers a portion of the whole TimeLine document).
  109.  * 
  110.  * In the InstrumentDrawCable function, take out the lines which draws the anchors,
  111.  * as these are no longer in the canvas display.
  112.  * 
  113.  * In the DrawTimeLine function, initialize the sec value with respect to the actual
  114.  * start time corresponding to the start of the canvas.
  115.  * 
  116.  * Revision 0.55  91/06/25  17:28:36  chua
  117.  * Replaced occurrences of the constant HalfSecondScale by the value 5, as the constant is no longer
  118.  * used.
  119.  * In the DrawNote routine, scale x and the width according to the zoom level so that the note is placed
  120.  * in the correct position on the canvas.
  121.  * In the DrawTimeLine routine, use a different algorithm for calculating the time labels for the
  122.  * time intervals.
  123.  * In the InstrumentDrawNotes routine, check if a note is selected.  If it is, draw it sunken.  If not,
  124.  * draw it raised.
  125.  * 
  126.  * Revision 0.54  91/06/04  17:37:16  chua
  127.  * Added the copyright comments in the beginning of the file.
  128.  * 
  129.  * Revision 0.53  91/06/03  11:11:52  chua
  130.  * Make changes to accomodate multiple documents.  This involves identifying
  131.  * which is the current active window, that is, the one where the last mouse
  132.  * click was done.
  133.  * 
  134.  * Revision 0.52  91/05/29  14:33:51  chua
  135.  * Replace lines 311-314 in the InstrumentDrawIcon routine with a call to InstrumentMute, which
  136.  * checks if the instrument mute indicator is to be drawn over the application icon for that
  137.  * instrument.
  138.  * 
  139.  * Revision 0.51  91/05/28  12:09:58  chua
  140.  * In the InstrumentDrawIcon procedure, check if mute is set to ON for that instrument.  If so, call the
  141.  * InstrumentMuteOn routine to draw the mute indicator (the word "MUTE") besides the icon for that
  142.  * instrument.
  143.  * 
  144.  * Revision 0.50  91/05/24  16:36:41  chua
  145.  * *** empty log message ***
  146.  * 
  147.  * Revision 0.49  91/05/23  17:38:57  chua
  148.  * *** empty log message ***
  149.  * 
  150.  * Revision 0.48  91/05/22  16:40:08  chua
  151.  * 
  152.  * 
  153.  * Revision 0.47  91/05/22  13:56:01  chua
  154.  * 
  155.  * 
  156.  * Revision 0.46  91/05/22  11:40:55  chua
  157.  * 
  158.  * 
  159.  * Revision 0.45  91/05/17  16:57:51  chua
  160.  * *** empty log message ***
  161.  * 
  162.  * Revision 0.44  91/05/17  16:56:56  chua
  163.  * *** empty log message ***
  164.  * 
  165.  * Revision 0.43  91/05/17  16:52:17  chua
  166.  * *** empty log message ***
  167.  * 
  168.  * Revision 0.42  1991/04/24  00:59:11  chua
  169.  * Some minor changes in the parameters when calling the DrawBox routine from inside the
  170.  * DrawNote function.  The width is reduced by 1, as it turns out the original was inaccurate.
  171.  *
  172.  * A new function, FreeInstrumentList is added.  It takes an instrument list head pointer as
  173.  * an argument and frees all the nodes in the list, including all the notes lists.
  174.  *
  175.  * Revision 0.41  1991/04/08  20:59:33  chua
  176.  * The DrawNote function is changed to accept a new parameter, 'type', which indicates if the note is to be
  177.  * drawn 'Raised' or 'Sunken'.  This is achieved by having a different foreground color (lighter for 'Raised'
  178.  * and darker for 'Sunken') and having the borders drawn differently (refer to DrawBox routine).
  179.  * Also, two additional fields are added to the instrument data structure.
  180.  * infoNote points to the note structure that is currently selected in the info panel list.
  181.  * selectedInfoNote gives the relative position of this selected note in the notes list of an instrument.
  182.  *
  183.  * The name of the function InstrumentDrawTimeLine is changed to DrawTimeLine, since this function is used
  184.  * just once for the TimeLine application and not once for each instrument.
  185.  *
  186.  * Revision 0.40  1991/04/01  01:56:33  chua
  187.  * This file contains functions for drawing most of the objects in the TimeLine Editor, and also functions
  188.  * to create a new instrument node and find an instrument node.  The functions are:
  189.  * InstrumentNew - create a new instrument node and initialize the values.
  190.  * FindInstrument - return a pointer to an instrument node given its relative position in the instrument list.
  191.  * DrawBox - draws a border rectangle around a box.
  192.  * DrawNote - this draws a rectangle which represents a note on the TimeLine.
  193.  * InstrumentDrawNotes - draws all the notes belonging to an instrument.
  194.  * InstrumentDrawCable - draws the cable belonging to an instrument.
  195.  * DrawTimeLine - draws the timeline (on the TimeCanvas) with the time markings on it.
  196.  * InstrumentDrawIcon - draws the icon for an instrument on the AppCanvas.
  197.  * InstrumentDraw - draws the cable and notes for an instrument (by calling the two functions above
  198.  *                  (InstrumentDrawNotes and InstrumentDrawCable).
  199.  * */
  200.  
  201. static char instrumentrcsid[] = "$Header: /Source/Media/collab/TimeLine/RCS/instrument.c,v 1.2 91/10/03 17:39:01 chua Exp Locker: drapeau $";
  202.  
  203. #include "main.h"
  204.  
  205. /* 
  206.  * This function draws the border for a box.  The arguments passed in are the display and drawable of the canvas to be drawn in,
  207.  * the coordinates for the top-left and bottom-right corners of the box, and a type which indicates if the box should be drawn 'raised' or
  208.  * 'sunken'.
  209.  * 'Raised' means the top and left borders are drawn in white, and the other two in black, giving the box a 3-D raised look.
  210.  * 'Sunken' means the top and left borders are drawn in black, and the other two in white, giving the box a 3-D sunken look.
  211.  * If type is 'Waiting', it is treated the same way as 'Sunken'.
  212.  * Called by DrawNote and InstrumentDrawIcon (instrument.c)
  213.  */
  214. void DrawBox(dpy, xid, x1, y1, x2, y2, type, tlFrame)
  215.      Display *dpy;
  216.      Drawable xid;
  217.      int x1, y1, x2, y2, type;
  218.      TimeLineFramePtr tlFrame;
  219. {
  220.   XPoint *points = (XPoint*) malloc (sizeof (XPoint) *3);        /* Array of point coordinates to be passed to the XDrawLines routine */
  221.   
  222.   if (type == Raised)                            /* Draw the top and left borders first */
  223.     XSetForeground(dpy, tlFrame->gc, (long)tlFrame->pixelTable[White]);
  224.   else 
  225.     XSetForeground(dpy, tlFrame->gc, (long)tlFrame->pixelTable[Black]);
  226.   points[0].x = x1;
  227.   points[0].y = y2;
  228.   points[1].x = x1;
  229.   points[1].y = y1;
  230.   points[2].x = x2;
  231.   points[2].y = y1;
  232.   XDrawLines(dpy, xid, tlFrame->gc, points, 3, CoordModeOrigin);
  233.   if (type == Raised)                            /* Now draw the right and bottom borders */
  234.     XSetForeground(dpy, tlFrame->gc, (long)tlFrame->pixelTable[Black]);
  235.   else 
  236.     XSetForeground(dpy, tlFrame->gc, (long)tlFrame->pixelTable[White]);
  237.   points[0].x = x2;
  238.   points[0].y = y1;
  239.   points[1].x = x2;
  240.   points[1].y = y2;
  241.   points[2].x = x1;
  242.   points[2].y = y2;
  243.   XDrawLines(dpy, xid, tlFrame->gc, points, 3, CoordModeOrigin);
  244. }
  245.  
  246. /*
  247.  * Routine to draw a note.  Currently just draws a note in the raised mode.
  248.  * First, the foreground color is set to Grey92, then the rectangle representing the note is drawn.
  249.  * The DrawBox function is then called to draw the border, given it the 'raised' look.
  250.  * x, y are the coordinates for the top left corner of the note, and width is the length of the note.
  251.  * type indicates if the note should be Raised or Sunken.
  252.  * Called by InstrumentDrawNotes (instrument.c) and AddandDisplayNewNote (note.c)
  253.  */
  254. DrawNote(x, y, width, type, tlFrame)
  255.      int x, y, width, type;
  256.      TimeLineFramePtr tlFrame;
  257. {
  258.   int drawWidth;
  259.   int newX;
  260.  
  261.   newX = (x / tlFrame->zoomLevel) - tlFrame->canvasStart;        /* Draw the note on the proper position in the canvas, depending on the */
  262.   drawWidth = width / tlFrame->zoomLevel;                /* zoom level */
  263.   if (drawWidth < 2) 
  264.     drawWidth = 2;
  265.   if (type == Raised)                            /* Check if note should be Raised or Sunken */
  266.     XSetForeground(tlFrame->dpyDraw, tlFrame->gc, (long)tlFrame->pixelTable[Grey92]); /* and set the foreground color accordingly */
  267.   else 
  268.     XSetForeground(tlFrame->dpyDraw, tlFrame->gc, (long)tlFrame->pixelTable[Grey65]);
  269.   XFillRectangle(tlFrame->dpyDraw, tlFrame->xidDraw, tlFrame->gc, newX, y, drawWidth, NoteHeight); /* Draw the note */
  270.   DrawBox(tlFrame->dpyDraw, tlFrame->xidDraw, newX + 1, y+1, newX+drawWidth, y+NoteHeight-2, type, tlFrame); /* Draw the border */
  271. }
  272.  
  273. /*
  274.  * This function will create a new instrument node (please refer to the header for instrument.h for a description of the instrument and note data
  275.  * structures).  It takes as arguments the relative position of the instrument in the instrument list (in the order registered with the Port Manager), and 
  276.  * the port number of the application that this instrument represents.  It then initializes the fields of the instrument data structure.  Again, please
  277.  * refer to instrument.h for a description of what each field represents.
  278.  * Called by OpenAppsInitialize (openApps.c)
  279.  */
  280. Instrument* InstrumentNew (relativePosition, port, tlFrame, appName)
  281.      int relativePosition;
  282.      Port *port;
  283.      TimeLineFramePtr tlFrame;
  284.      char *appName;
  285. {
  286.   Instrument *instrument = (Instrument *) malloc (sizeof (Instrument));
  287.   
  288.   instrument->relativePosition = relativePosition;
  289.   instrument->cableStart = (IconHeight + IconGap) * relativePosition + FirstCableYPosition;
  290.   instrument->port = (Port *) malloc(sizeof(Port));
  291.   instrument->port->appName = (char *) malloc (MAXPATHLEN);
  292.   instrument->port->hostName = (char *) malloc (MAXPATHLEN);
  293.   instrument->port->portNumber = -1;
  294.   if (port == NULL) 
  295.   {
  296.     strcpy(instrument->port->appName, appName);
  297.     strcpy(instrument->port->hostName, "App not open");
  298.   }
  299.   else 
  300.   {
  301.     instrument->port->portNumber = port->portNumber;
  302.     strcpy(instrument->port->hostName, port->hostName);
  303.     strcpy(instrument->port->appName, port->appName);
  304.   }
  305.   if (strcmp(instrument->port->hostName, "App not open") != 0) 
  306.     instrument->sender = NewSender(port);
  307.   instrument->icon = (Pixmap) xv_get(OpenAppsFindIcon(instrument),  /* Get the pixmap image of the icon */
  308.                 SERVER_IMAGE_PIXMAP);
  309.   instrument->numnotes = 0;
  310.   instrument->playNote = 0;
  311.   instrument->partialNote = 0;
  312.   instrument->firstNote = NULL;
  313.   instrument->infoNote = NULL;
  314.   instrument->currentNote = NULL;
  315.   instrument->selectedInfoNote = -1;
  316.   instrument->editInfo = NULL;
  317.   instrument->next = NULL;
  318.   InitEditInfoWindow(instrument, tlFrame);                    /* Create the info popup window */
  319.   return instrument;
  320. }
  321.  
  322. /* 
  323.  * This function will add a new instrument to the instrument list.
  324.  */
  325. void AddInstrument(port, tlFrame)
  326.      Port *port;
  327.      TimeLineFramePtr tlFrame;
  328. {
  329.   Instrument *lastInstrument;                        /* Current last instrument in the list */
  330.   
  331.   if (tlFrame->numberOfApps == 0)                    /* First application to be added */
  332.     tlFrame->instHead = (Instrument *) InstrumentNew(0, port, tlFrame, NULL);
  333.   else                                    /* Add this application on to the application list */
  334.   {
  335.     lastInstrument = (Instrument *) FindInstrument(tlFrame->numberOfApps - 1, tlFrame);
  336.     lastInstrument->next = (Instrument *) InstrumentNew(tlFrame->numberOfApps, port, tlFrame, NULL);
  337.   }
  338.   tlFrame->numberOfApps++;                        /* Increment the number of open apps counter */
  339. }
  340.  
  341. /* 
  342.  * Function that will take a head pointer to an instrument list and frees all the instruments and their note lists.
  343.  * Called by CopyToClipboard (select.c), UpdateAppsHandler (openApps.c)
  344.  */
  345. void FreeInstrumentList(tlFrame)
  346.      TimeLineFramePtr tlFrame;
  347. {
  348.   Instrument *instrument, *ifree;
  349.   Sender *sender;
  350.  
  351.   ClearAllNotes(tlFrame);
  352.   instrument = tlFrame->instHead;
  353.   while (instrument != NULL) 
  354.   {
  355.     ifree = instrument;
  356.     xv_destroy_safe(instrument->editInfo->EditInfoWindow);
  357.     if (strcmp(instrument->port->hostName, "App not open") != 0) 
  358.     {
  359.       sender = NewSender(instrument->port);
  360.       if (sender != NULL) 
  361.       {
  362.     DestroySender(instrument->sender);
  363.     DestroySender(sender);
  364.       }
  365.       free(instrument->port);
  366.     }
  367.     instrument = instrument->next;
  368.     free (ifree);
  369.   }
  370.   tlFrame->instHead = (Instrument *) NULL;
  371.   tlFrame->numberOfApps = 0;
  372.   tlFrame->selectedInstrument = (Instrument *) NULL;
  373.   tlFrame->noteInstrument = (Instrument *) NULL;
  374. }
  375.   
  376. /*
  377.  * Function that will return a pointer to the appropriate instrument node given its relative position in the instrument list.
  378.  * Called by DrawCanvasEventHandler and AppCanvasEventHandler (canvas.c).
  379.  */
  380. Instrument *FindInstrument(relativePosition, tlFrame)
  381.      int relativePosition;
  382.      TimeLineFramePtr tlFrame;
  383. {
  384.   int         i;
  385.   Instrument*     currentInst;
  386.   
  387.   if (relativePosition < 0) 
  388.   {
  389.     return NULL;
  390.   }
  391.   currentInst = tlFrame->instHead;                        /* To find the appropriate instrument node */
  392.   for (i=0; i < relativePosition && currentInst != NULL; i++)
  393.     currentInst = currentInst->next;
  394.   return currentInst;
  395. }
  396.  
  397. /*
  398.  * This function draws all the notes for a given instrument.  It goes down the notes list in the instrument data structure and
  399.  * calls the DrawNote routine to draw each note.
  400.  * Called by InstrumentDraw (instrument.c)
  401.  */
  402. void InstrumentDrawNotes(instrument, tlFrame)
  403.      Instrument *instrument;
  404.      TimeLineFramePtr tlFrame;
  405. {
  406.   Note *note;
  407.   int canvasStart;
  408.   int TimeLineLength;
  409.   int type;
  410.  
  411.   canvasStart = tlFrame->canvasStart * tlFrame->zoomLevel;
  412.   TimeLineLength = tlFrame->TimeLineLength * tlFrame->zoomLevel;
  413.   for (note = instrument->firstNote; note != NULL; note = note->next) 
  414.   {
  415.     if ((note->start >= canvasStart && note->start <= canvasStart + TimeLineLength) ||
  416.     (note->end >= canvasStart && note->end <= canvasStart + TimeLineLength)) 
  417.     {
  418.       type = Raised;
  419.       if (note == instrument->infoNote) 
  420.     type = Sunken;
  421.       DrawNote(note->start, instrument->cableStart - NoteHeight/2,
  422.            note->end - note->start, type, tlFrame);
  423.     }
  424.   }
  425. }
  426.  
  427. /*
  428.  * Draw the instrument cable and its ends (anchors).
  429.  * Called by InstrumentDraw (instrument.c)
  430.  */
  431. void InstrumentDrawCable(instrument, tlFrame)
  432.      Instrument *instrument;
  433.      TimeLineFramePtr tlFrame;
  434. {
  435.   XSetForeground(tlFrame->dpyDraw, tlFrame->gc, (long)tlFrame->pixelTable[Black]); /* Set to draw in black */
  436.   XFillRectangle(tlFrame->dpyDraw,tlFrame->xidDraw,tlFrame->gc, 0,  /* Draw the cable */
  437.          instrument->cableStart - CableHeight/2,
  438.          tlFrame->TimeLineLength, CableHeight);
  439. }
  440.  
  441. /* 
  442.  * Draws the pause markers.
  443.  */
  444. void DrawPauseMarkers(tlFrame)
  445.      TimeLineFramePtr tlFrame;
  446. {
  447.   Pause *pause;
  448.   int canvasStart;
  449.   int TimeLineLength;
  450.   int startPosition;
  451.  
  452.   canvasStart = tlFrame->canvasStart * tlFrame->zoomLevel;
  453.   TimeLineLength = tlFrame->TimeLineLength * tlFrame->zoomLevel;
  454.   XSetForeground(tlFrame->dpyDraw, tlFrame->gc, (long)tlFrame->pixelTable[Red]);
  455.   for (pause = tlFrame->pauseHead; pause != NULL; pause = pause->next) 
  456.   {
  457.     if (pause->position >= canvasStart && pause->position <= canvasStart + TimeLineLength)
  458.     {
  459.       startPosition = (pause->position / tlFrame->zoomLevel) - tlFrame->canvasStart;
  460.       XDrawLine(tlFrame->dpyDraw, tlFrame->xidDraw, tlFrame->gc, 
  461.         startPosition, 0,
  462.         startPosition, tlFrame->numberOfApps * 72 + FirstCableYPosition);
  463.     }
  464.   }
  465. }
  466.  
  467. /*
  468.  * This function draws the timeline with the time labels in intervals depending on the zoom level.
  469.  * Called by TimeCanvasRepaintHandler (canvas.c)
  470.  */
  471. void DrawTimeLine(tlFrame)
  472.      TimeLineFramePtr tlFrame;
  473. {
  474.   long i, min, sec;
  475.   char msg[10];
  476.   
  477.   XSetForeground(tlFrame->dpyTime, tlFrame->gc, 
  478.          (long)tlFrame->pixelTable[Black]);            /* Set the foreground color to black */
  479.   XFillRectangle(tlFrame->dpyTime,tlFrame->xidTime,tlFrame->gc,        /* Draw the cable */
  480.          0,
  481.          TimeLineY - 1,
  482.          tlFrame->TimeLineLength, 2);
  483.   for (i=0; i < tlFrame->TimeLineLength; i += PixelsPerSecond * TimeLineInterval) /* Draw the time markers */
  484.     XFillRectangle(tlFrame->dpyTime, tlFrame->xidTime, tlFrame->gc, i, TimeLineY - (MarkerHeight/2),
  485.            MarkerWidth, MarkerHeight);
  486.   min = 0;                                /* Display the time intervals */
  487.   sec = tlFrame->canvasStart * tlFrame->zoomLevel / PixelsPerSecond;
  488.   for (i=32; i < tlFrame->TimeLineLength; i += PixelsPerSecond * TimeLineInterval) 
  489.   {                                    /* The number 32 is obtained by trial and error.  It is the starting x coodinate */
  490.                                     /* of the first time interval */
  491.     sec += TimeLineInterval * tlFrame->zoomLevel;            /* Update the time */
  492.     while (sec >= 60) 
  493.     {
  494.       sec -= 60;
  495.       min ++;
  496.     }
  497.     sprintf (msg, "%02d:%02d", min, sec);
  498.     XDrawString(tlFrame->dpyTime, tlFrame->xidTime, tlFrame->gc, i, TimeLineY + 17, msg, 5);
  499.   }
  500. }
  501.  
  502. /*
  503.  * This function will draw the icon bitmap of an instrument on the AppCanvas.
  504.  * It takes as arguments a pointer to the instrument note, and a type which indicates if the icon is to be drawn in the raised or sunken mode, or
  505.  * in wait state (background red).
  506.  * First, the OpenAppsFindIcon function is called to get the bitmap image of the icon.
  507.  * After setting the appropriate background color depending on the drawing mode (raised or sunken), the XCopyPlane Xlib routine is called which
  508.  * copies the bitmap onto the canvas.
  509.  * The DrawBox routine is then called to draw the borders, giving the icon the raised or sunken look.
  510.  * Finally, the InstrumentMute procedure is called to see if the mute symbol is to be drawn across the application icon.
  511.  * Called by AppCanvasEventHandler and AppCanvasRepaintHandler (canvas.c)
  512.  */
  513. void InstrumentDrawIcon(instrument, type, tlFrame)
  514.      Instrument *instrument;
  515.      int type;
  516.      TimeLineFramePtr tlFrame;
  517. {
  518.   XSetForeground(tlFrame->dpyApp, tlFrame->gc, 
  519.          (long)tlFrame->pixelTable[Black]);            /* Set the foreground color to black */
  520.   if (type == Raised)                            /* Set the background color to either Grey92 (a lighter grey) or */
  521.     XSetBackground(tlFrame->dpyApp, tlFrame->gc,            /* Grey65 (a darker grey) depending on whether the icon is to be */
  522.            (long)tlFrame->pixelTable[Grey92]);            /* drawn raised or sunken */
  523.   else if (type == Sunken)
  524.     XSetBackground(tlFrame->dpyApp, tlFrame->gc, (long)tlFrame->pixelTable[Grey65]);
  525.   else 
  526.     XSetBackground(tlFrame->dpyApp, tlFrame->gc, (long)tlFrame->pixelTable[Red]);
  527.   XCopyPlane(tlFrame->dpyApp, instrument->icon, tlFrame->xidApp, tlFrame->gc, /* Copy the 1-bit deep icon into the 8-bit deep canvaswindow */
  528.          0, 0, IconHeight, IconHeight, IconXOffset,
  529.          instrument->cableStart - IconHeight/2, 1);
  530.   DrawBox(tlFrame->dpyApp, tlFrame->xidApp, IconXOffset,        /* Draw the borders for the icon */
  531.       instrument->cableStart - 32, 
  532.       IconXOffset + IconHeight, 
  533.       instrument->cableStart + IconHeight/2, type, tlFrame);
  534.   InstrumentMute (instrument, tlFrame);
  535. }
  536.  
  537. /*
  538.  * Draw the instrument cable and notes for the specified instrument.
  539.  * Called by DrawCanvasRepaintHandler (canvas.c)
  540.  */
  541. void InstrumentDraw(instrument, tlFrame)
  542.      Instrument *instrument;
  543.      TimeLineFramePtr tlFrame;
  544. {
  545.   InstrumentDrawCable(instrument, tlFrame);
  546.   DrawPauseMarkers(tlFrame);
  547.   InstrumentDrawNotes(instrument, tlFrame);
  548. }
  549.